package window;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections4.CollectionUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Author: youdao.hww
 * @Date: 10/17/24
 * @Desc:
 */
public class Test {

    // 新窗口保护时间（10分钟）
    private static final long NEW_WINDOW_PROTECTION_TIME = 10 * 60 * 1000; // 10 minutes in milliseconds
    // 新窗口选中比例（50%）
    private static final double NEW_WINDOW_SELECTION_RATIO = 0.5;
    // 全局计数器
    private static final AtomicInteger selectedNewWindowCount = new AtomicInteger(0);

    public static void main(String[] args) {

        // 假设你有一个 List<WindowInfoDTO> collects
        List<WindowInfoDTO> allowWindowInfoDTOList = Arrays.asList(
                new WindowInfoDTO(1, 2, 10, false, new Date(System.currentTimeMillis() - 5 * 60 * 1000)), // 已经开放5分钟
                new WindowInfoDTO(2, 1, 0, false, new Date()), // 新开放的窗口
                new WindowInfoDTO(3, 1, 0, false, new Date()), // 新开放的窗口
                new WindowInfoDTO(4, 2, 5, false, new Date(System.currentTimeMillis() - 15 * 60 * 1000)), // 已经开放15分钟
                new WindowInfoDTO(5, 2, 15, false, new Date(System.currentTimeMillis() - 20 * 60 * 1000)) // 已经开放20分钟
        );


        // 模拟多个 schedule
        for (int i = 0; i < 100; i++) {
            // 查找符合条件的对象
            WindowInfoDTO bestWindow = findBestWindow(allowWindowInfoDTOList);
            // 处理结果
            if (bestWindow != null) {
                System.out.println("Best Window: " + bestWindow);
            } else {
                System.out.println("No suitable window found.");
            }
        }

    }


    public static WindowInfoDTO findBestWindow(List<WindowInfoDTO> allowWindowInfoDTOList) {
        if (CollectionUtils.isNotEmpty(allowWindowInfoDTOList)) {
            // 先按 isNewOpen 排序，isNewOpen=1 的优先级更高
            // 再按 peopleNumber 排序
            allowWindowInfoDTOList.sort(Comparator.comparing(WindowInfoDTO::getIsNewOpen)
                    .thenComparing(WindowInfoDTO::getPeopleNumber));

            // 找到所有具有相同优先级的窗口
            List<WindowInfoDTO> bestCandidates = new ArrayList<>();

            Integer bestIsNewOpen = allowWindowInfoDTOList.get(0).getIsNewOpen();
            Integer bestPeopleNumber = allowWindowInfoDTOList.get(0).getPeopleNumber();

            for (WindowInfoDTO window : allowWindowInfoDTOList) {
                if (window.getIsNewOpen().equals(bestIsNewOpen) && window.getPeopleNumber().equals(bestPeopleNumber)) {
                    bestCandidates.add(window);
                } else {
                    break;
                }
            }
            System.out.println("----bestCandidates-----"+ JSONObject.toJSONString(bestCandidates));

            // 随机选择一个窗口
            Random random = new Random();
            WindowInfoDTO bestWindow = bestCandidates.get(random.nextInt(bestCandidates.size()));


            // 检查是否在保护时间内
            if (bestWindow.getIsNewOpen() == 1 && isWithinProtectionTime(bestWindow.getOpenTime())) {
                int totalSchedules = 2; // 假设有10个schedule
                int maxAllowedSelections = (int) (totalSchedules * NEW_WINDOW_SELECTION_RATIO);
                if (selectedNewWindowCount.incrementAndGet() > maxAllowedSelections) {
                    // 超过最大允许选中的次数，选择下一个最佳窗口
                    bestWindow = getNextBestWindow(allowWindowInfoDTOList, bestWindow);
                }
            }
            return bestWindow;
        }
        return null;
    }

    private static boolean isWithinProtectionTime(Date openTime) {
        long currentTime = System.currentTimeMillis();
        return (currentTime - openTime.getTime()) <= NEW_WINDOW_PROTECTION_TIME;
    }

    private static WindowInfoDTO getNextBestWindow(List<WindowInfoDTO> allowWindowInfoDTOList, WindowInfoDTO currentBest) {
        // 从剩余的窗口中选择下一个最佳窗口
        List<WindowInfoDTO> remainingWindows = allowWindowInfoDTOList.stream()
                .filter(window -> !window.equals(currentBest))
                .sorted(Comparator.comparing(WindowInfoDTO::getIsNewOpen)
                        .thenComparing(WindowInfoDTO::getPeopleNumber))
                .collect(Collectors.toList());

        if (!remainingWindows.isEmpty()) {
            return remainingWindows.get(0);
        }
        return null;
    }

}
